package cn.admin.config.common.protocol;

import cn.admin.hessian.io.JavaDeserializationBridge;
import com.caucho.hessian.io.AbstractDeserializer;
import com.caucho.hessian.io.AbstractHessianInput;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

public class ProtocolPacketDecoder<T> extends AbstractDeserializer {

    private static final Logger log = LoggerFactory.getLogger(ProtocolPacketDecoder.class);
    private final Class<T> klazz;
    private final Field transientElements;

    ProtocolPacketDecoder(Class<T> klazz) {
        this.klazz = klazz;

        try {
            this.transientElements = ProtocolPacket.class.getDeclaredField("elements");
            this.transientElements.setAccessible(true);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Class<T> getType() {
        return this.klazz;
    }

    @Override
    public Object readMap(AbstractHessianInput hin) throws IOException {

        ProtocolPacket pp;

        try {
            pp = (ProtocolPacket) JavaDeserializationBridge.newInstance(klazz);
            hin.addRef(pp);
            this.transientElements.set(pp,new ArrayList<>(0));
        } catch (IllegalAccessException | InstantiationException |
                InvocationTargetException | IOException e) {
            throw new IOException(e);
        }

        hin.readString();
        List<?> elements = (List<?>) hin.readObject();
        hin.readMapEnd();
        for (Object e : elements) {
            if (e instanceof ProtocolElement) {
                pp.addElement((ProtocolElement) e);
            } else {
                log.error("########## Unrecognized protocol element:" + e);
            }
        }
        return pp;
    }

}
